﻿#if NETSTANDARD2_0 || NETCOREAPP3_0
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Net.Http;
#endif
using System;
using System.Collections.Generic;

namespace Longbow.Cache
{
    /// <summary>
    /// CacheManager静态操作提供类
    /// </summary>
    public static class CacheManager
    {
#if NETSTANDARD2_0 || NETCOREAPP3_0
        private static Lazy<ICache> _lazy;
#else
        private static readonly Lazy<ICache> _lazy = new Lazy<ICache>(() => new DefaultCache());
#endif

        /// <summary>
        /// 获得 缓存所有键值集合
        /// </summary>
        public static IEnumerable<string> Keys { get { return _lazy.Value.Keys; } }

        /// <summary>
        ///
        /// </summary>
        public static IEnumerable<ICacheCorsItem> CorsSites { get { return _lazy.Value.CorsSites; } }

        #region 静态方法
#if NETSTANDARD2_0 || NETCOREAPP3_0
        internal static void RegisterCacheManager(this IServiceCollection services)
        {
            _lazy = new Lazy<ICache>(() =>
            {
                var provider = services.BuildServiceProvider();
                var httpContextAccessor = provider.GetRequiredService<IHttpContextAccessor>();
                var options = provider.GetRequiredService<IOptionsMonitor<CacheOptions>>();
                var factory = provider.GetRequiredService<IHttpClientFactory>();
                return new DefaultCache(options, httpContextAccessor, factory);
            });
        }
#endif

        /// <summary>
        /// 获取或者添加一个缓存项
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">缓存项键值</param>
        /// <param name="valueFactory">创建缓存项回调方法</param>
        /// <param name="profileKey">配置文件中缓存键值</param>
        /// <returns></returns>
        public static T GetOrAdd<T>(string key, Func<string, T> valueFactory, string profileKey = null)
        {
            return _lazy.Value.GetOrAdd(key, valueFactory, profileKey);
        }

        /// <summary>
        /// 获取或者添加一个缓存项
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="option">缓存项配置 ICacheOption 实例</param>
        /// <param name="valueFactory">创建缓存项回调方法</param>
        /// <returns></returns>
        public static T GetOrAdd<T>(ICacheOption option, Func<string, T> valueFactory)
        {
            return _lazy.Value.GetOrAdd(option, valueFactory);
        }

        /// <summary>
        /// 添加或者更新一个缓存项
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">缓存项键值</param>
        /// <param name="valueFactory">创建缓存项回调方法</param>
        /// <param name="updateFactory">更新缓存项回调方法</param>
        /// <param name="profileKey">配置文件中缓存键值</param>
        /// <returns></returns>
        public static T AddOrUpdate<T>(string key, Func<string, T> valueFactory, Func<string, T, T> updateFactory, string profileKey = null)
        {
            return _lazy.Value.AddOrUpdate(key, valueFactory, updateFactory, profileKey);
        }

        /// <summary>
        /// 添加或者更新一个缓存项
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="option">缓存项配置 ICacheOption 实例</param>
        /// <param name="valueFactory">创建缓存项回调方法</param>
        /// <param name="updateFactory">更新缓存项回调方法</param>
        /// <returns></returns>
        public static T AddOrUpdate<T>(ICacheOption option, Func<string, T> valueFactory, Func<string, T, T> updateFactory)
        {
            return _lazy.Value.AddOrUpdate(option, valueFactory, updateFactory);
        }

        /// <summary>
        /// 通过指定缓存键值获取缓存项
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">缓存键值</param>
        /// <returns>缓存项</returns>
        public static T Get<T>(string key)
        {
            return _lazy.Value.Get<T>(key);
        }

        /// <summary>
        /// 通过指定缓存项键值集合清除缓存
        /// </summary>
        /// <param name="keys">缓存项键值集合</param>
        public static void Clear(IEnumerable<string> keys)
        {
            _lazy.Value.Clear(keys);
        }

        /// <summary>
        /// 清除指定缓存项键值缓存，缓存项键值为空时清除所有缓存
        /// </summary>
        public static void Clear(string key = null)
        {
            if (string.IsNullOrEmpty(key)) _lazy.Value.Clear();
            else _lazy.Value.Clear(key);
        }

        /// <summary>
        /// 通过配置文件跨域清理缓存
        /// </summary>
        /// <param name="keys"></param>
        public static void CorsClear(IEnumerable<string> keys)
        {
            _lazy.Value.CorsClear(keys);
        }

        /// <summary>
        /// 获得缓存项总数
        /// </summary>
        /// <returns></returns>
        public static int Count => _lazy.Value.Count;

        /// <summary>
        /// 获取缓存项集合
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<ICacheItem> ToList()
        {
            return _lazy.Value.ToList();
        }
        #endregion
    }
}
